package com.suxin.utils;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;

/**
 * @author liqilin
 * @since 2021/9/9 10:54
 */
public class DateUtil {

    public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    public static Date plusDays(Date date, long days) {
        return transferDateTime(transferDateTime(date).plusDays(days));
    }

    public static Date minusDays(Date date, long days) {
        return transferDateTime(transferDateTime(date).minusDays(days));
    }

    public static Date minusMinutes(Date date, long minutes) {
        return transferDateTime(transferDateTime(date).minusMinutes(minutes));
    }

    public static Date plusMinutes(Date date, long minutes) {
        return transferDateTime(transferDateTime(date).plusMinutes(minutes));
    }

    public static Date plusSeconds(Date date, long seconds) {
        return transferDateTime(transferDateTime(date).plusSeconds(seconds));
    }

    public static Date of(int year, Month month, int dayOfMonth, int hour, int minute, int second) {
        return transferDateTime(LocalDateTime.of(year, month, dayOfMonth, hour, minute, second));
    }

    public static Date of(LocalDate date, int hour, int minute, int second) {
        return transferDateTime(LocalDateTime.of(date.getYear(), date.getMonth(), date.getDayOfMonth(), hour, minute, second));
    }

    public static Date transferDateTime(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static LocalDateTime transferDateTime(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    public static LocalDateTime transferDateTime(String dateTime) {
        return LocalDateTime.parse(dateTime, DATETIME_FORMATTER);
    }

    public static LocalDate transferDate(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()).toLocalDate();
    }

    public static Date transferDate(LocalDate date) {
        return transferDateTime(date.atStartOfDay());
    }

    public static Date transferDate(String date) {
        return transferDate(LocalDate.parse(date, DATE_FORMATTER));
    }

    public static Date atStartOfDay(Date date) {
        return transferDateTime(transferDate(date).atStartOfDay());
    }

    public static Date atEndOfDay(Date date) {
        return transferDateTime(transferDate(date).atTime(23, 59, 59));
    }

    public static String formatDate(LocalDate date) {
        return date.format(DATE_FORMATTER);
    }

    public static String formatDate(Date date) {
        return transferDate(date).format(DATE_FORMATTER);
    }

    public static String formatDateTime(LocalDateTime dateTime) {
        return dateTime.format(DATETIME_FORMATTER);
    }

    public static Date min(Date date1, Date date2) {
        return date1.compareTo(date2) > 0 ? date2 : date1;
    }

    public static Date max(Date date1, Date date2) {
        return date1.compareTo(date2) < 0 ? date2 : date1;
    }

    /**
     * 时间戳（毫秒）转datetime
     *
     * @param timeStamp 时间戳（毫秒）
     * @return datetime
     */
    public static LocalDateTime of(long timeStamp) {
        return LocalDateTime.ofEpochSecond(timeStamp / 1000, 0, ZoneOffset.ofHours(8));
    }

    /**
     * 判断选择的日期本月的第几天
     */
    public static int getWeeksByChooseDay() {
        Calendar calSelected = Calendar.getInstance();
        return calSelected.get(Calendar.DAY_OF_MONTH);
    }


    /**
     * 获取这周的开始时间 & 结束时间
     *
     * @param now
     * @return
     */
    public static Date[] getWeekDay(LocalDate now) {
        // 起始时间
        LocalDate s1 = now.plus(-now.get(ChronoField.DAY_OF_WEEK) + 1, ChronoUnit.DAYS);
        return new Date[]{
                Date.from(s1.atStartOfDay(ZoneId.systemDefault()).toInstant()),
                Date.from(now.atStartOfDay(ZoneId.systemDefault()).toInstant())
        };
    }

    /**
     * 获取本月的开始时间 & 结束时间
     *
     * @param now
     * @return
     */
    public static Date[] getMonthDay(LocalDate now) {
        LocalDate s1 = now.withDayOfMonth(1);
        return new Date[]{
                Date.from(s1.atStartOfDay(ZoneId.systemDefault()).toInstant()),
                Date.from(s1.plusMonths(1L).plus(-1L, ChronoUnit.DAYS).atStartOfDay(ZoneId.systemDefault()).toInstant())
        };
    }

    /**
     * 获取指定月份的开始一天和最后一天
     * @param localDate
     * @return
     */
    public static LocalDate[] getMonthFirstAndEndDay(LocalDate localDate) {
        return new LocalDate[]{
                localDate.with(TemporalAdjusters.firstDayOfMonth()),localDate.with(TemporalAdjusters.lastDayOfMonth())
        };
    }

    /**
     * 是否是本月的最后一天
     * @param localDate
     * @return
     */
    public static boolean isLastDayOfMonth(LocalDate localDate) {
        return localDate.compareTo(localDate.with(TemporalAdjusters.lastDayOfMonth())) == 0;
    }

}
